package com.boil.qz.safekavass.dao;

import com.boil.util.Constants;
import com.boil.util.Page;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.*;

/**
 * Created by ChenYong on 2017-06-13.
 * <br>
 * Mybatis Dao（适合用于查询）。
 */
@Repository
public class MybatisDao {
    /**
     * 注入 Mybatis 模版
     */
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    /**
     * 获取 Mybatis 模版。
     *
     * @return Mybatis 模版
     */
    public SqlSessionTemplate getMybatisTemplate() {
        return sqlSessionTemplate;
    }

    /**
     * 获取 Session 工厂。
     *
     * @return
     */
    public SqlSessionFactory getSessionFactory() {
        return sqlSessionTemplate.getSqlSessionFactory();
    }

    /**
     * 打开 Session。
     *
     * @return Session
     */
    public SqlSession openSession() {
        return getSessionFactory().openSession();
    }

    /**
     * 保存数据。
     *
     * @param sqlId sql 语句 ID
     * @return 插入的记录数
     */
    public int insert(String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            return Constants.VALUE_0;
        }

        return sqlSessionTemplate.insert(sqlId);
    }

    /**
     * 保存数据。
     *
     * @param sqlId sql 语句 ID
     * @param param 参数
     * @return 插入的记录数
     */
    public int insert(String sqlId, Object param) {
        if (StringUtils.isBlank(sqlId) || (param == null)) {
            return Constants.VALUE_0;
        }

        return sqlSessionTemplate.insert(sqlId, param);
    }

    /**
     * 保存数据。
     *
     * @param sqlId  sql 语句 ID
     * @param params 参数
     * @return 插入的记录数
     */
    public <T> int insert(String sqlId, List<T> params) {
        if (StringUtils.isBlank(sqlId) || //
                (params == null) || //
                params.isEmpty()) {
            return Constants.VALUE_0;
        }

        int count = Constants.VALUE_0;

        for (T param : params) {
            count += insert(sqlId, param);
        }

        return count;
    }

    /**
     * 保存数据。
     *
     * @param sqlId  sql 语句 ID
     * @param params 参数
     * @return 插入的记录数
     */
    public <T> int insert(String sqlId, Set<T> params) {
        if (StringUtils.isBlank(sqlId) || //
                (params == null) || //
                params.isEmpty()) {
            return Constants.VALUE_0;
        }

        int count = Constants.VALUE_0;

        for (T param : params) {
            count += insert(sqlId, param);
        }

        return count;
    }

    /**
     * 删除数据。
     *
     * @param sqlId sql 语句 ID
     * @return 被删除的记录数
     */
    public int delete(String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            return Constants.VALUE_0;
        }

        return sqlSessionTemplate.delete(sqlId);
    }

    /**
     * 删除数据。
     *
     * @param sqlId sql 语句 ID
     * @param param 参数
     * @return 被删除的记录数
     */
    public int delete(String sqlId, Object param) {
        if (StringUtils.isBlank(sqlId) || (param == null)) {
            return Constants.VALUE_0;
        }

        return sqlSessionTemplate.delete(sqlId, param);
    }

    /**
     * 假删除数据。
     *
     * @param sqlId sql 语句 ID
     * @return 被假删除的记录数
     */
    public int fakeDelete(String sqlId) {
        return this.update(sqlId);
    }

    /**
     * 假删除数据。
     *
     * @param sqlId sql 语句 ID
     * @param param 参数
     * @return 被假删除的记录数
     */
    public int fakeDelete(String sqlId, Object param) {
        return this.update(sqlId, param);
    }

    /**
     * 更新数据。
     *
     * @param sqlId sql 语句 ID
     * @return 被更新的记录数
     */
    public int update(String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            return Constants.VALUE_0;
        }

        return sqlSessionTemplate.update(sqlId);
    }

    /**
     * 更新数据。
     *
     * @param sqlId sql 语句 ID
     * @param param 参数
     * @return 被更新的记录数
     */
    public int update(String sqlId, Object param) {
        if (StringUtils.isBlank(sqlId) || (param == null)) {
            return Constants.VALUE_0;
        }

        return sqlSessionTemplate.update(sqlId, param);
    }

    /**
     * 更新数据。
     *
     * @param sqlId  sql 语句 ID
     * @param params 参数
     * @return 更新的记录数
     */
    public <T> int update(String sqlId, List<T> params) {
        if (StringUtils.isBlank(sqlId) || //
                (params == null) || //
                params.isEmpty()) {
            return Constants.VALUE_0;
        }

        int count = Constants.VALUE_0;

        for (T param : params) {
            count += update(sqlId, param);
        }

        return count;
    }

    /**
     * 更新数据。
     *
     * @param sqlId  sql 语句 ID
     * @param params 参数
     * @return 更新的记录数
     */
    public <T> int update(String sqlId, Set<T> params) {
        if (StringUtils.isBlank(sqlId) || //
                (params == null) || //
                params.isEmpty()) {
            return Constants.VALUE_0;
        }

        int count = Constants.VALUE_0;

        for (T param : params) {
            count += update(sqlId, param);
        }

        return count;
    }

    /**
     * 查询 <code>List</code>。
     *
     * @param sqlId sql 语句 ID
     * @return <code>List</code>
     */
    public <T> List<T> selectList(String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            return new ArrayList<T>();
        }

        return sqlSessionTemplate.selectList(sqlId);
    }

    /**
     * 查询 <code>List</code>。
     *
     * @param sqlId sql 语句 ID
     * @param param 参数
     * @return <code>List</code>
     */
    public <T> List<T> selectList(String sqlId, Object param) {
        if (StringUtils.isBlank(sqlId) || (param == null)) {
            return new ArrayList<T>();
        }

        return sqlSessionTemplate.selectList(sqlId, param);
    }

    /**
     * 分页查询 <code>List</code>。
     *
     * @param sqlId     sql 语句 ID
     * @param param     参数
     * @param rowBounds 逻辑分页（查出所有记录再按偏移量和 limit 取结果，这种分页性能很差！）
     * @return <code>List</code>
     */
    public <T> List<T> selectList(String sqlId, Object param, RowBounds rowBounds) {
        if (StringUtils.isBlank(sqlId) || //
                (param == null) || //
                (rowBounds == null)) {
            return new ArrayList<T>();
        }

        return sqlSessionTemplate.selectList(sqlId, param, rowBounds);
    }

    /**
     * 查询 <code>Map</code>。
     *
     * @param sqlId  sql 语句 ID
     * @param mapKey 键值
     * @return <code>Map</code>
     */
    public <K, V> Map<K, V> selectMap(String sqlId, String mapKey) {
        if (StringUtils.isBlank(sqlId) || StringUtils.isBlank(mapKey)) {
            return new HashMap<K, V>();
        }

        return sqlSessionTemplate.selectMap(sqlId, mapKey);
    }

    /**
     * 查询 <code>Map</code>。
     *
     * @param sqlId  sql 语句 ID
     * @param param  参数
     * @param mapKey 键值
     * @return <code>Map</code>
     */
    public <K, V> Map<K, V> selectMap(String sqlId, Object param, String mapKey) {
        if (StringUtils.isBlank(sqlId) || //
                (param == null) || //
                StringUtils.isBlank(mapKey)) {
            return new HashMap<K, V>();
        }

        return sqlSessionTemplate.selectMap(sqlId, param, mapKey);
    }

    /**
     * 分页查询 <code>Map</code>。
     *
     * @param sqlId     sql 语句 ID
     * @param param     参数
     * @param mapKey    键值
     * @param rowBounds 逻辑分页（查出所有记录再按偏移量和 limit 取结果，这种分页性能很差！）
     * @return <code>Map</code>
     */
    public <K, V> Map<K, V> selectMap(String sqlId, Object param, String mapKey, RowBounds rowBounds) {
        if (StringUtils.isBlank(sqlId) || //
                (param == null) || //
                StringUtils.isBlank(mapKey) || //
                (rowBounds == null)) {
            return new HashMap<K, V>();
        }

        return sqlSessionTemplate.selectMap(sqlId, param, mapKey, rowBounds);
    }

    /**
     * 查询实体。
     *
     * @param sqlId sql 语句 ID
     * @return 实体
     */
    public <T> T selectOne(String sqlId) {
        if (StringUtils.isBlank(sqlId)) {
            return null;
        }

        return sqlSessionTemplate.selectOne(sqlId);
    }

    /**
     * 查询实体。
     *
     * @param sqlId sql 语句 ID
     * @param param 参数
     * @return 实体
     */
    public <T> T selectOne(String sqlId, Object param) {
        if (StringUtils.isBlank(sqlId) || (param == null)) {
            return null;
        }

        return sqlSessionTemplate.selectOne(sqlId, param);
    }

    /**
     * 分页查询。
     * <br>
     * 结果自动保存在分页实例中。
     *
     * @param sqlId sql 语句 ID
     * @param page  分页实例
     */
    @SuppressWarnings("unchecked")
    public <T> void selectInPage(String sqlId, Page<T> page) {
        page.setResults((List<T>) this.selectList(sqlId, page));
    }
}